package com.codingchili.logging.controller;

import com.codingchili.logging.Service;
import com.codingchili.logging.configuration.LogContext;
import com.codingchili.logging.model.*;
import io.vertx.core.Promise;

import com.codingchili.core.context.TimerSource;
import com.codingchili.core.listener.CoreHandler;
import com.codingchili.core.listener.Request;
import com.codingchili.core.logging.Logger;
import com.codingchili.core.protocol.*;

import static com.codingchili.common.Strings.NODE_STATISTICS;
import static com.codingchili.core.context.FutureHelper.untyped;
import static com.codingchili.core.protocol.RoleMap.PUBLIC;
import static com.codingchili.logging.Service.MODEL_INTERVAL_MS;

/**
 * Handles incoming requests for statistics.
 */
@Roles(PUBLIC)
public class StatisticsHandler implements CoreHandler {
    private final Protocol<?> protocol = new Protocol<>(this);
    private final LogContext context;
    private StatisticModel model = new StatisticModel(); // serve empty model until stats are loaded.
    private final Logger logger;

    public StatisticsHandler(LogContext context) {
        this.context = context;
        this.logger = context.logger(getClass());
    }

    @Override
    public void start(Promise<Void> start) {
        context.vertx()
                .sharedData().<String, StatisticModel>getLocalAsyncMap(Service.SHARED_MAP)
                .onSuccess(map -> {
                    context.periodic(TimerSource.of(MODEL_INTERVAL_MS), v -> map.get(StatisticModel.id())
                            .onSuccess(model -> {
                                if (model != null) {
                                    this.model = model;
                                }
                            }).onFailure(logger::onError));
                }).onComplete(untyped(start));
    }

    @Api
    public void accounts(StatisticsRequest request) {
        request.write(new AccountsResponse(model.getAccounts()));
    }

    @Api
    public void leaderboard(StatisticsRequest request) {
        request.write(new LeaderboardResponse(model.getLeaderboard(), model.getCharacters()));
    }

    @Api
    public void distribution(StatisticsRequest request) {
        request.write(model.realm(request.realm()));
    }

    @Override
    public void handle(Request request) {
        protocol.process(new StatisticsRequest(request));
    }

    @Override
    public String address() {
        return NODE_STATISTICS;
    }
}